package com.anjubao.parking.municipal.parkinglot.controller;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;

import com.anjubao.parking.municipal.common.dto.ApiCode;
import com.anjubao.parking.municipal.common.utils.MunicipalParkingUtils;
import com.anjubao.parking.municipal.parkinglot.dto.ParkingLotDto;
import com.anjubao.parking.municipal.parkinglot.dto.ParkingLotReturnCodeDto;
import com.anjubao.parking.municipal.parkinglot.dto.ParkingLotStatDto;
import com.anjubao.parking.municipal.parkinglot.form.*;
import com.anjubao.parking.municipal.parkinglot.mapper.ParkingLotBillRuleMapper;
import com.anjubao.parking.municipal.parkinglot.model.ParkingLotBillRule;
import com.anjubao.parking.municipal.parkinglot.model.ParkingLotStatus;
import com.anjubao.parking.municipal.parkinglot.service.ParkingLotStatusService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.*;

import com.anjubao.parking.municipal.common.dto.ApiResult;
import com.anjubao.parking.municipal.common.utils.BeanUtils;
import com.anjubao.parking.municipal.parkinglot.model.ParkingLot;
import com.anjubao.parking.municipal.parkinglot.service.ParkingLotService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

/**
 * 停车场基本信息API
 * @author Atom.zyu
 *
 */
@RestController
@RequestMapping("/parking-lots")
@Api(value="Parkinglot-Service模块",tags = {"停车场管理接口"})
public class ParkingLotController {
	private static final Logger logger = LoggerFactory.getLogger(ParkingLotController.class);
	@Autowired
	private ParkingLotService parkingLotService;
	@Autowired
	private ParkingLotStatusService parkingLotStatusService;
	@Resource
	private ParkingLotBillRuleMapper parkingLotBillRuleMapper;

	/**
	 * 创建
	 *
	 * @param form
	 * @return
	 */
	@PostMapping(value = "/")
	@ApiOperation(value = "4.1.1创建停车场",notes = "",code = 2000)
	@ApiImplicitParams({
			@ApiImplicitParam(name="form",required = true,dataType = "ParkingLotAddForm",paramType = "body")
	})
	@ApiResponses(value = {
			@ApiResponse(code = 5000, message = "操作失败"),
	})
	public ApiResult<ParkingLotReturnCodeDto> createParkingLot(@RequestBody @Valid  ParkingLotAddForm form) {

		logger.info("creating new parking lot {} ", form);
		ParkingLot entityCreated = parkingLotService.saveParkingLot(BeanUtils.transform(ParkingLot.class, form),form.getBillRuleCodes());
		ParkingLotStatus parkingLotStatus=new ParkingLotStatus().
				setCode(entityCreated.getCode()).setId(entityCreated.getId()).setFreeSlots(entityCreated.getTotalSlots()).
				setName(entityCreated.getName()).setStatus(1).setIsOnline(1);
		parkingLotStatusService.save(parkingLotStatus);
		return ApiResult.success(new ParkingLotReturnCodeDto().setParkingLotCode(entityCreated.getCode()));
	}


	@PutMapping("/{parkingLotCode}")
	@ApiOperation(value = "4.1.2修改停车场信息")
	@ApiImplicitParams({
			@ApiImplicitParam(name="form",required = true,dataType = "ParkingLotEditForm",paramType = "body"),
			@ApiImplicitParam(name="parkingLotCode",value = "停车场code",required = true,dataType = "String",paramType = "path")
	})
	@ApiResponses(value = {
			@ApiResponse(code = 5000, message = "操作失败"),
	})
	/**
	 * 更新
	 *
	 * @param parkingLotCode
	 * @param form
	 * @return
	 */
	public ApiResult<ParkingLotReturnCodeDto> updateParkingLot(@PathVariable String parkingLotCode, @RequestBody @Valid ParkingLotEditForm form) {
		logger.info("updating parking lot {} ", form);
		ParkingLot parkingLot = BeanUtils.transform(ParkingLot.class, form);
		parkingLot.setCode(parkingLotCode);
		ParkingLot updated = parkingLotService.saveParkingLot(parkingLot,form.getBillRuleCodes());
		return ApiResult.success(new ParkingLotReturnCodeDto().setParkingLotCode(updated.getCode()));
	}



	@GetMapping("/{parkingLotCode}")
	@ApiOperation(value = "4.1.3查看单个停车场详细信息接口")
	@ApiImplicitParams({
			@ApiImplicitParam(name="parkingLotCode",value = "停车场code",required = true,dataType = "String",paramType = "path")
	})
	@ApiResponses(value = {
			@ApiResponse(code = 5000, message = "操作失败"),
	})
	/**
	 * 查询
	 *
	 * @param parkingLotCode    停车场编号
	 * @return
	 */
	public ApiResult<ParkingLotDto> getParkingLot(@PathVariable String parkingLotCode) {
		logger.info("get parking lot by code {}", parkingLotCode);
		ParkingLot parkingLot = parkingLotService.getById(MunicipalParkingUtils.getIdByCode(parkingLotCode));
		ParkingLotDto parkingLotDto=BeanUtils.transform(ParkingLotDto.class,parkingLot);
		parkingLotDto.setParkingLotCode(parkingLot.getCode());
		return ApiResult.success(parkingLotDto);
	}

	/**
	 * 查询
	 *
	 * @param form   PositionScreeningParkingLotForm
	 * @return
	 */
	@GetMapping("/")
	@ApiOperation(value = "4.1.4根据经纬度筛选停车场信息接口")
	@ApiResponses(value = {
			@ApiResponse(code = 5000, message = "操作失败"),
	})
	public ApiResult<List<ParkingLotDto>> positionScreeningParkingLot(@Valid PositionScreeningParkingLotForm form, BindingResult result) {
		if(result.hasErrors()){
			List<ObjectError> ls=result.getAllErrors();
			return new ApiResult<>(ApiCode.STATUS_INTERNAL_ERROR.getCode(), String.valueOf(ls.get(0)));
		}
		logger.info("screening parking lot by conditions {}", form);
		Page<ParkingLot> page=new Page<>();
		page.setSize(form.getPageSize());
		page.setCurrent(form.getPage());
		IPage<ParkingLot> parkingLotLists = parkingLotService.positionScreeningParkingLot(page,form);
		List<ParkingLotDto> parkingLotDtolits=parkingLotLists2ParkingLotDtoLists( parkingLotLists.getRecords());
		return ApiResult.success(parkingLotDtolits, (int) parkingLotLists.getTotal());
	}

	@GetMapping("/areas")
	@ApiOperation(value = "4.1.5根据省市区筛选停车场信息接口")
	@ApiImplicitParams({
			@ApiImplicitParam(name="parkingLotType",value = "停车场类型(1:封闭式停车场，2:路内停车场)", dataType = "int" ,paramType = "query",allowableValues = "1,2",type = "integer"),
			@ApiImplicitParam(name="parkingLotStatus",value = "停车场状态(0:正常,1:禁用)", dataType = "int" ,paramType = "query",allowableValues = "0,1",type = "integer"),
			@ApiImplicitParam(name="parkingStatus",value = "车位状态 0:车位不足 1:有位 2:已满", dataType = "int" ,paramType = "query",allowableValues = "0,1,2",type = "integer")
	})
	@ApiResponses(value = {
			@ApiResponse(code = 5000, message = "操作失败"),
	})
	/**
	 * 查询
	 *
	 * @param form
	 * @return
	 */
	public ApiResult<List<ParkingLotDto>> areaScreeningParkingLot( AreaScreeningParkingLotForm form) {
		if(form.getCityId()==null&&form.getDistrictId()==null&&form.getProvinceId()==null){
			return new ApiResult<>(ApiCode.STATUS_INTERNAL_ERROR.getCode(), "省市区ID不允许同时为空");
		}
		logger.info("screening parking lot by conditions {}", form);
		Page<ParkingLotDto> page=new Page<>();
		page.setSize(form.getPageSize());
		page.setCurrent(form.getPage());
        IPage<ParkingLotDto> parkingLotLists = parkingLotService.areaScreeningParkingLot(page,form);
		return ApiResult.success(parkingLotLists.getRecords(), (int) parkingLotLists.getTotal());
	}


	@GetMapping("/parking-lot-statistical")
	@ApiOperation(value = "4.1.6 区域停车场车位统计接口（总车位/已用车位/空余车位）")
	@ApiResponses(value = {
			@ApiResponse(code = 5000, message = "操作失败"),
	})
	/**
	 * 查询
	 *
	 * @param form
	 * @return
	 */
	public ApiResult<List<ParkingLotStatDto>> parkingLotStatistical( AreaScreeningParkingLotForm form) {
		if(form.getCityId()==null&&form.getDistrictId()==null&&form.getProvinceId()==null){
			return new ApiResult<>(ApiCode.STATUS_INTERNAL_ERROR.getCode(), "省市区ID不允许同时为空");
		}
		logger.info("statistical parking lot by conditions {}", form);
		List<ParkingLotStatDto> parkingLotLists = parkingLotService.parkingLotStatistical(form);
		return ApiResult.success(parkingLotLists,parkingLotLists.size());
	}



	@PostMapping(value = "/heartbeat")
	@ApiOperation(value = "2.1.4车场心跳数据接口",notes = "")
	@ApiImplicitParams({
			@ApiImplicitParam(name="form",required = true,dataType = "ParkingLotHeartbeatForm",paramType = "body")
	})
	@ApiResponses(value = {
			@ApiResponse(code = 5000, message = "操作失败"),
	})
	/**
	 * 创建
	 *
	 * @param form
	 * @return
	 */
	public ApiResult<ParkingLotReturnCodeDto> parkingLotHeartBeat(@RequestBody @Valid ParkingLotHeartbeatForm form, BindingResult result) {
		if(result.hasErrors()){
			List<ObjectError> ls=result.getAllErrors();
			return new ApiResult<>(ApiCode.STATUS_INTERNAL_ERROR.getCode(), String.valueOf(ls.get(0)));
		}
		logger.info("updating parking lot {} ", form);
		ParkingLot parkingLot=new ParkingLot();
		parkingLot.setTotalSlots(form.getTotalSlots());
		parkingLot.setCode(form.getParkingLotCode());
		parkingLot.setReservedSlots(form.getRemainTotalSlots());
		ParkingLot	entityUpdated=parkingLotService.saveParkingLot(parkingLot,null);
		return ApiResult.success(new ParkingLotReturnCodeDto().setParkingLotCode(entityUpdated.getCode()));
	}


	private List<ParkingLotDto> parkingLotLists2ParkingLotDtoLists(List<ParkingLot> parkingLotLists){
		List<ParkingLotDto> parkingLotDtolits=new ArrayList<>();
		for(ParkingLot parkingLot:parkingLotLists){
			parkingLotDtolits.add(BeanUtils.transform(ParkingLotDto.class,parkingLot));
			parkingLotDtolits.get(parkingLotDtolits.size()-1).setParkingLotCode(parkingLot.getCode());
		}
		return  parkingLotDtolits;
	}

}
